package com.cencat.common.utils;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.InputStreamSource;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;

import jakarta.mail.MessagingException;
import jakarta.mail.internet.MimeMessage;
import java.io.File;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;

/**
 * 邮件工具类
 * 提供邮件发送功能，支持简单邮件、HTML邮件、附件邮件等
 * 
 * @author cencat
 * @since 2024-01-01
 */

public class EmailUtils {

    private static final Logger log = LoggerFactory.getLogger(EmailUtils.class);

    private static JavaMailSender mailSender;
    private static String defaultFrom;
    private static final Executor emailExecutor = Executors.newFixedThreadPool(5);

    private EmailUtils() {
        // 私有构造函数，防止实例化
    }

    /**
     * 初始化邮件工具
     * 
     * @param javaMailSender 邮件发送器
     * @param from           默认发件人
     */
    public static void init(JavaMailSender javaMailSender, String from) {
        mailSender = javaMailSender;
        defaultFrom = from;
    }

    /**
     * 发送简单文本邮件
     * 
     * @param to      收件人
     * @param subject 主题
     * @param content 内容
     * @return 发送结果
     */
    public static EmailResult sendSimpleMail(String to, String subject, String content) {
        return sendSimpleMail(defaultFrom, to, subject, content);
    }

    /**
     * 发送简单文本邮件
     * 
     * @param from    发件人
     * @param to      收件人
     * @param subject 主题
     * @param content 内容
     * @return 发送结果
     */
    public static EmailResult sendSimpleMail(String from, String to, String subject, String content) {
        try {
            validateMailSender();
            validateEmailAddress(to);
            
            SimpleMailMessage message = new SimpleMailMessage();
            message.setFrom(from);
            message.setTo(to);
            message.setSubject(subject);
            message.setText(content);
            message.setSentDate(new java.util.Date());
            
            mailSender.send(message);
            
            log.info("简单邮件发送成功: from={}, to={}, subject={}", from, to, subject);
            return EmailResult.success("邮件发送成功");
        } catch (Exception e) {
            log.error("简单邮件发送失败: from={}, to={}, subject={}, error={}", from, to, subject, e.getMessage());
            return EmailResult.failure("邮件发送失败: " + e.getMessage());
        }
    }

    /**
     * 发送简单文本邮件（多个收件人）
     * 
     * @param toList  收件人列表
     * @param subject 主题
     * @param content 内容
     * @return 发送结果
     */
    public static EmailResult sendSimpleMail(List<String> toList, String subject, String content) {
        return sendSimpleMail(defaultFrom, toList, subject, content);
    }

    /**
     * 发送简单文本邮件（多个收件人）
     * 
     * @param from    发件人
     * @param toList  收件人列表
     * @param subject 主题
     * @param content 内容
     * @return 发送结果
     */
    public static EmailResult sendSimpleMail(String from, List<String> toList, String subject, String content) {
        try {
            validateMailSender();
            if (toList == null || toList.isEmpty()) {
                return EmailResult.failure("收件人列表不能为空");
            }
            
            for (String to : toList) {
                validateEmailAddress(to);
            }
            
            SimpleMailMessage message = new SimpleMailMessage();
            message.setFrom(from);
            message.setTo(toList.toArray(new String[0]));
            message.setSubject(subject);
            message.setText(content);
            message.setSentDate(new java.util.Date());
            
            mailSender.send(message);
            
            log.info("批量简单邮件发送成功: from={}, toCount={}, subject={}", from, toList.size(), subject);
            return EmailResult.success("邮件发送成功");
        } catch (Exception e) {
            log.error("批量简单邮件发送失败: from={}, toCount={}, subject={}, error={}", 
                     from, toList != null ? toList.size() : 0, subject, e.getMessage());
            return EmailResult.failure("邮件发送失败: " + e.getMessage());
        }
    }

    /**
     * 发送HTML邮件
     * 
     * @param to          收件人
     * @param subject     主题
     * @param htmlContent HTML内容
     * @return 发送结果
     */
    public static EmailResult sendHtmlMail(String to, String subject, String htmlContent) {
        return sendHtmlMail(defaultFrom, to, subject, htmlContent);
    }

    /**
     * 发送HTML邮件
     * 
     * @param from        发件人
     * @param to          收件人
     * @param subject     主题
     * @param htmlContent HTML内容
     * @return 发送结果
     */
    public static EmailResult sendHtmlMail(String from, String to, String subject, String htmlContent) {
        try {
            validateMailSender();
            validateEmailAddress(to);
            
            MimeMessage message = mailSender.createMimeMessage();
            MimeMessageHelper helper = new MimeMessageHelper(message, true, EmailConstants.DEFAULT_CHARSET);
            
            helper.setFrom(from);
            helper.setTo(to);
            helper.setSubject(subject);
            helper.setText(htmlContent, true); // true表示HTML格式
            helper.setSentDate(new java.util.Date());
            
            mailSender.send(message);
            
            log.info("HTML邮件发送成功: from={}, to={}, subject={}", from, to, subject);
            return EmailResult.success("邮件发送成功");
        } catch (MessagingException | RuntimeException e) {
            log.error("HTML邮件发送失败: from={}, to={}, subject={}, error={}", from, to, subject, e.getMessage());
            return EmailResult.failure("邮件发送失败: " + e.getMessage());
        }
    }

    /**
     * 发送带附件的邮件
     * 
     * @param to           收件人
     * @param subject      主题
     * @param content      内容
     * @param attachments  附件列表
     * @return 发送结果
     */
    public static EmailResult sendMailWithAttachments(String to, String subject, String content, 
                                                      List<EmailAttachment> attachments) {
        return sendMailWithAttachments(defaultFrom, to, subject, content, attachments, false);
    }

    /**
     * 发送带附件的邮件
     * 
     * @param from        发件人
     * @param to          收件人
     * @param subject     主题
     * @param content     内容
     * @param attachments 附件列表
     * @param isHtml      是否HTML格式
     * @return 发送结果
     */
    public static EmailResult sendMailWithAttachments(String from, String to, String subject, String content, 
                                                      List<EmailAttachment> attachments, boolean isHtml) {
        try {
            validateMailSender();
            validateEmailAddress(to);
            
            MimeMessage message = mailSender.createMimeMessage();
            MimeMessageHelper helper = new MimeMessageHelper(message, true, EmailConstants.DEFAULT_CHARSET);
            
            helper.setFrom(from);
            helper.setTo(to);
            helper.setSubject(subject);
            helper.setText(content, isHtml);
            helper.setSentDate(new java.util.Date());
            
            // 添加附件
            if (attachments != null && !attachments.isEmpty()) {
                for (EmailAttachment attachment : attachments) {
                    addAttachment(helper, attachment);
                }
            }
            
            mailSender.send(message);
            
            log.info("带附件邮件发送成功: from={}, to={}, subject={}, attachmentCount={}", 
                    from, to, subject, attachments != null ? attachments.size() : 0);
            return EmailResult.success("邮件发送成功");
        } catch (MessagingException | RuntimeException e) {
            log.error("带附件邮件发送失败: from={}, to={}, subject={}, error={}", from, to, subject, e.getMessage());
            return EmailResult.failure("邮件发送失败: " + e.getMessage());
        }
    }

    /**
     * 发送模板邮件
     * 
     * @param to           收件人
     * @param subject      主题
     * @param templatePath 模板路径
     * @param variables    模板变量
     * @return 发送结果
     */
    public static EmailResult sendTemplateMail(String to, String subject, String templatePath, 
                                               Map<String, Object> variables) {
        return sendTemplateMail(defaultFrom, to, subject, templatePath, variables);
    }

    /**
     * 发送模板邮件
     * 
     * @param from         发件人
     * @param to           收件人
     * @param subject      主题
     * @param templatePath 模板路径
     * @param variables    模板变量
     * @return 发送结果
     */
    public static EmailResult sendTemplateMail(String from, String to, String subject, String templatePath, 
                                               Map<String, Object> variables) {
        try {
            // 读取模板内容
            String templateContent = FileUtils.readFileContent(templatePath);
            
            // 替换模板变量
            String content = replaceTemplateVariables(templateContent, variables);
            
            // 发送HTML邮件
            return sendHtmlMail(from, to, subject, content);
        } catch (Exception e) {
            log.error("模板邮件发送失败: from={}, to={}, subject={}, templatePath={}, error={}", 
                     from, to, subject, templatePath, e.getMessage());
            return EmailResult.failure("模板邮件发送失败: " + e.getMessage());
        }
    }

    /**
     * 异步发送邮件
     * 
     * @param emailTask 邮件任务
     * @return 异步结果
     */
    public static CompletableFuture<EmailResult> sendMailAsync(EmailTask emailTask) {
        return CompletableFuture.supplyAsync(() -> {
            try {
                return emailTask.execute();
            } catch (Exception e) {
                log.error("异步邮件发送失败: error={}", e.getMessage());
                return EmailResult.failure("异步邮件发送失败: " + e.getMessage());
            }
        }, emailExecutor);
    }

    /**
     * 批量异步发送邮件
     * 
     * @param emailTasks 邮件任务列表
     * @return 异步结果列表
     */
    public static List<CompletableFuture<EmailResult>> sendMailBatchAsync(List<EmailTask> emailTasks) {
        return emailTasks.stream()
                .map(EmailUtils::sendMailAsync)
                .collect(java.util.stream.Collectors.toList());
    }

    /**
     * 添加附件
     * 
     * @param helper     邮件助手
     * @param attachment 附件
     * @throws MessagingException 消息异常
     */
    private static void addAttachment(MimeMessageHelper helper, EmailAttachment attachment) throws MessagingException {
        if (attachment.getFile() != null) {
            // 文件附件
            FileSystemResource file = new FileSystemResource(attachment.getFile());
            helper.addAttachment(attachment.getName(), file);
        } else if (attachment.getFilePath() != null) {
            // 文件路径附件
            FileSystemResource file = new FileSystemResource(new File(attachment.getFilePath()));
            helper.addAttachment(attachment.getName(), file);
        } else if (attachment.getContent() != null) {
            // 内容附件
            helper.addAttachment(attachment.getName(), attachment.getContent(), attachment.getContentType());
        }
    }

    /**
     * 替换模板变量
     * 
     * @param template  模板内容
     * @param variables 变量映射
     * @return 替换后的内容
     */
    private static String replaceTemplateVariables(String template, Map<String, Object> variables) {
        if (template == null || variables == null || variables.isEmpty()) {
            return template;
        }
        
        String result = template;
        for (Map.Entry<String, Object> entry : variables.entrySet()) {
            String placeholder = "${" + entry.getKey() + "}";
            String value = entry.getValue() != null ? entry.getValue().toString() : "";
            result = result.replace(placeholder, value);
        }
        return result;
    }

    /**
     * 验证邮件发送器
     */
    private static void validateMailSender() {
        if (mailSender == null) {
            throw new IllegalStateException("邮件发送器未初始化，请先调用init方法");
        }
    }

    /**
     * 验证邮箱地址
     * 
     * @param email 邮箱地址
     */
    private static void validateEmailAddress(String email) {
        if (!CencatStringUtils.isValidEmail(email)) {
            throw new IllegalArgumentException("无效的邮箱地址: " + email);
        }
    }

    /**
     * 邮件附件类
     */
    public static class EmailAttachment {
        private String name;
        private File file;
        private String filePath;
        private Object content;
        private String contentType;

        public EmailAttachment() {
        }

        public EmailAttachment(String name, File file) {
            this.name = name;
            this.file = file;
        }

        public EmailAttachment(String name, String filePath) {
            this.name = name;
            this.filePath = filePath;
        }

        public EmailAttachment(String name, Object content, String contentType) {
            this.name = name;
            this.content = content;
            this.contentType = contentType;
        }

        // Getters and Setters
        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public File getFile() {
            return file;
        }

        public void setFile(File file) {
            this.file = file;
        }

        public String getFilePath() {
            return filePath;
        }

        public void setFilePath(String filePath) {
            this.filePath = filePath;
        }

        public InputStreamSource getContent() {
            return (InputStreamSource) content;
        }

        public void setContent(Object content) {
            this.content = content;
        }

        public String getContentType() {
            return contentType;
        }

        public void setContentType(String contentType) {
            this.contentType = contentType;
        }
    }

    /**
     * 邮件任务接口
     */
    @FunctionalInterface
    public interface EmailTask {
        EmailResult execute();
    }

    /**
     * 邮件发送结果类
     */
    public static class EmailResult {
        private boolean success;
        private String message;
        private LocalDateTime sendTime;
        private String messageId;
        private Exception exception;

        public EmailResult() {
            this.sendTime = LocalDateTime.now();
        }

        public EmailResult(boolean success, String message) {
            this();
            this.success = success;
            this.message = message;
        }

        public static EmailResult success(String message) {
            return new EmailResult(true, message);
        }

        public static EmailResult failure(String message) {
            return new EmailResult(false, message);
        }

        public static EmailResult failure(String message, Exception exception) {
            EmailResult result = new EmailResult(false, message);
            result.setException(exception);
            return result;
        }

        // Getters and Setters
        public boolean isSuccess() {
            return success;
        }

        public void setSuccess(boolean success) {
            this.success = success;
        }

        public String getMessage() {
            return message;
        }

        public void setMessage(String message) {
            this.message = message;
        }

        public LocalDateTime getSendTime() {
            return sendTime;
        }

        public void setSendTime(LocalDateTime sendTime) {
            this.sendTime = sendTime;
        }

        public String getMessageId() {
            return messageId;
        }

        public void setMessageId(String messageId) {
            this.messageId = messageId;
        }

        public Exception getException() {
            return exception;
        }

        public void setException(Exception exception) {
            this.exception = exception;
        }
    }

    /**
     * 邮件常量类
     */
    public static class EmailConstants {
        
        // 默认配置
        public static final String DEFAULT_CHARSET = "UTF-8";
        public static final String DEFAULT_CONTENT_TYPE = "text/html;charset=UTF-8";
        
        // 邮件类型
        public static final String CONTENT_TYPE_TEXT = "text/plain";
        public static final String CONTENT_TYPE_HTML = "text/html";
        
        // 附件类型
        public static final String ATTACHMENT_TYPE_FILE = "application/octet-stream";
        public static final String ATTACHMENT_TYPE_IMAGE = "image/jpeg";
        public static final String ATTACHMENT_TYPE_PDF = "application/pdf";
        public static final String ATTACHMENT_TYPE_WORD = "application/msword";
        public static final String ATTACHMENT_TYPE_EXCEL = "application/vnd.ms-excel";
        
        // 大小限制
        public static final long MAX_ATTACHMENT_SIZE = 25 * 1024 * 1024; // 25MB
        public static final int MAX_RECIPIENTS = 100; // 最大收件人数量
        public static final int MAX_SUBJECT_LENGTH = 200; // 最大主题长度
        public static final int MAX_CONTENT_LENGTH = 1024 * 1024; // 最大内容长度 1MB
        
        // 模板变量格式
        public static final String TEMPLATE_VARIABLE_PREFIX = "${";
        public static final String TEMPLATE_VARIABLE_SUFFIX = "}";
        
        // 常用模板变量
        public static final String VAR_USER_NAME = "userName";
        public static final String VAR_COMPANY_NAME = "companyName";
        public static final String VAR_CURRENT_DATE = "currentDate";
        public static final String VAR_CURRENT_TIME = "currentTime";
        public static final String VAR_VERIFICATION_CODE = "verificationCode";
        public static final String VAR_RESET_LINK = "resetLink";
        
        private EmailConstants() {
            // 私有构造函数，防止实例化
        }
    }

    /**
     * 邮件模板构建器
     */
    public static class EmailTemplateBuilder {
        private String template;
        private final Map<String, Object> variables = new java.util.HashMap<>();

        public EmailTemplateBuilder(String template) {
            this.template = template;
        }

        public EmailTemplateBuilder variable(String key, Object value) {
            variables.put(key, value);
            return this;
        }

        public EmailTemplateBuilder userName(String userName) {
            return variable(EmailConstants.VAR_USER_NAME, userName);
        }

        public EmailTemplateBuilder companyName(String companyName) {
            return variable(EmailConstants.VAR_COMPANY_NAME, companyName);
        }

        public EmailTemplateBuilder currentDate(String currentDate) {
            return variable(EmailConstants.VAR_CURRENT_DATE, currentDate);
        }

        public EmailTemplateBuilder currentTime(String currentTime) {
            return variable(EmailConstants.VAR_CURRENT_TIME, currentTime);
        }

        public EmailTemplateBuilder verificationCode(String verificationCode) {
            return variable(EmailConstants.VAR_VERIFICATION_CODE, verificationCode);
        }

        public EmailTemplateBuilder resetLink(String resetLink) {
            return variable(EmailConstants.VAR_RESET_LINK, resetLink);
        }

        public String build() {
            return replaceTemplateVariables(template, variables);
        }
    }
}